import {defineComponent, nextTick, PropType, ref, watch} from "vue";
import type {ColRule, Control, TableTree, DataList, DictList} from "@/interfaces/components/Table";
import {ElTable, ElTableColumn, ElButton, ElTag, ElLoading} from "element-plus"
import Style from "@/styles/components/table.module.css";
import {getValue, randomStr} from "@/utils/utilities";
import {appStore} from "@/store/modules/app";
import {Template} from "@/interfaces/components/Table";
import { v4 as uuidv4 } from "uuid";

export default defineComponent({
    name: "CdlTable",
    props: {
        templateTree:{type: Object as PropType<TableTree<any>>, required: true},
        data: {type: Array, required: true},
        loading: {type: Boolean, required: false, default: false},
        controlWidth: {type: Number, required: false},
        defExpandAll: {type: Boolean, required: false, default: false},
        rowKey: {type: String, required: false},
        border: {type: Boolean, required: false, default: false},
        showOverflowTooltip: {type: Boolean, required: false, default: false},
        controlFixed: {type: Boolean, required: false, default: false},
        lazy: {type: Boolean, required: false, default: false},
        load: {type: Function as PropType<any>, required: false},
        treeProps: {type: Object as PropType<{children: string, hasChildren: string}>, required: false}
    },

    setup(props, {expose}){
        const app = appStore()
        const uuid = uuidv4()
        const onlyStr = randomStr()
        const tableEl = ref<InstanceType<typeof ElTable>>()
        const multipleSelection = ref<any[]>([])
        const {bodyTemplate, controlTemplate}: {bodyTemplate:Template<any>[], controlTemplate:Control[] | undefined} = parsingTemplateTree(props.templateTree)
        let demo: any = null
        if(props.loading !== undefined){
            watch(()=> props.loading, (value)=>{
                if(value) nextTick(()=>{
                    demo = ElLoading.service({ target: `.${onlyStr}`, text: "加载中..."
                        , background: "rgba(255,255,255,0.7)"})
                })
                else demo?.close()
            }, {immediate: true})
        }

        /**
         * 模板生成器
         * 最终会返回一个包含表头，表体的模板对象及操作栏
         * @param tree
         */
        function parsingTemplateTree(tree: TableTree<any>){
            let bodyTemplate: ColRule<any>[] =  tree.colRule
            let controlTemplate: Control[] | undefined = tree.control
            return {
                bodyTemplate,
                controlTemplate,
            }
        }
        /**
         * 通过字典类型创建对应样式
         * @param dict  字典类型
         * @param keyName
         */
        function analyticDictionary(dict: string | string[], keyName: string){
            function createElement(rowData: any){
                let data:DataList | undefined
                let type: string |undefined
                if(Array.isArray(dict)) type = getValue(rowData, dict[0])
                else type = dict
                app.dictList.forEach((item: DictList) =>{
                    if ((Array.isArray(dict)?item.dictId : item.dictType) === type) {
                        item.dataList.forEach(obj =>{
                            if(obj.dictValue == rowData[keyName]?.toString()) data = obj
                        })
                    }
                })
                if(data === undefined) return rowData[keyName]
                return <ElTag type={data.labelClass === "primary"? "": data.labelClass}>
                    {data.dictLabel}</ElTag>
            }
            return {
                default: (scope: any)=> createElement(scope.row)
            }
        }
        /**
         * 多选框数据改变
         * @param val
         */
        function handleSelectionChange(val: any[]){
            multipleSelection.value = val
        }
        /**
         * 当用户手动勾选数据行的 Checkbox 时触发的事件
         * @param val
         */
        function handleSelect(val: any){

        }
        const controlSlots = {
            default: (scope: any)=> <>
                {controlTemplate?.map((item: Control) =>{
                    if(item.pretreatment && !item.pretreatment(scope.row)){
                        return null
                    }
                    return <ElButton type={item.type}
                                     plain
                                     v-auth={item.auth}
                                     onClick={():void =>{
                                         item.method(item.prop? scope.row[item.prop] : scope.row)}} round>
                        {item.name}
                    </ElButton>
                })}
            </>
        }

        function crateSlot(slot: any, key: string){
            return {
                default: (scope: any)=> slot(key? scope.row[key] : scope.row)
            }
        }
        expose({
            multipleSelection
        })

        return ()=>(
            <ElTable data={props.data}
                     ref={tableEl}
                     className={onlyStr}
                     rowKey={props.rowKey}
                     border={props.border}
                     lazy={props.lazy}
                     load={props.load}
                     treeProps={props.treeProps}
                     onSelection-change={handleSelectionChange}
                     onSelect={handleSelect}
                     cellClassName={Style.cell_name} style={{width: "100%"}}>
                {
                    bodyTemplate.map((item: ColRule<any>) =>{
                        return <ElTableColumn prop={item.prop}
                                              label={item.ti}
                                              type={item.type}
                                              align={item.align}
                                              showOverflowTooltip={item.tooltip}
                                              formatter={item.format?
                                                  (row)=> item.format? item.format(item.prop? row[item.prop] : row)
                                                      : "格式化失败" : undefined}
                                              v-slots={item.slot? crateSlot(item.slot, item.prop || "")
                                                  : item.dict? analyticDictionary(item.dict, item.prop || "")
                                                      : null}
                                              width={item.width}
                                              minWidth={item.minWidth || 100}
                                              selectable={item.selectTable}
                        >
                        </ElTableColumn>
                    })
                }
                {
                    controlTemplate? <ElTableColumn label="操作"
                                                    v-slots={controlSlots}
                                                    align="center"
                                                    fixed={props.controlFixed? "right" : undefined}
                                                    width={props.controlWidth}></ElTableColumn> : null
                }
            </ElTable>
        )
    }
})
